//
//  TFUIModalPresentViewController.m
//  TFFoundation
//
//  Created by 夏之祥 on 2019/5/9.
//

#import "TFUIModalPresentViewController.h"
//util
#import <Masonry/Masonry.h>
#import "TFUIDefine.h"
#import <objc/runtime.h>

const float kTFUIModalPresentAnimationDuration = 0.4;

@interface TFUIModalPresentViewController ()

@property (nonatomic, copy) TFUIModalPresentViewControllerDismissCompletion dismissCompletion;

@end

@implementation TFUIModalPresentViewController

+ (instancetype)showWithContentView:(UIView *)contentView animationStyle:(TFUIModalPresentAnimationStyle)animationStyle animationDuration:(float)animationDuration dismissCompletion:(nullable TFUIModalPresentViewControllerDismissCompletion)dismissCompletion {
    TFUIModalPresentViewController *modalVC = [[self alloc] init];
    if (contentView) {
        modalVC.contentView = contentView;
    }
    modalVC.animationStyle = animationStyle;
    modalVC.animationDuration = animationDuration;
    modalVC.dismissCompletion = dismissCompletion;
    dispatch_async(dispatch_get_main_queue(), ^{
        [[TFUIDefine visibleViewController] presentViewController:modalVC animated:NO completion:nil];
    });
    return modalVC;
}

+ (instancetype)showWithContentView:(UIView *)contentView animationStyle:(TFUIModalPresentAnimationStyle)animationStyle animationDuration:(float)animationDuration {
    return [self showWithContentView:contentView animationStyle:animationStyle animationDuration:animationDuration dismissCompletion:nil];
}

+ (instancetype)showWithAnimationStyle:(TFUIModalPresentAnimationStyle)animationStyle {
    return [self showWithContentView:nil animationStyle:animationStyle animationDuration:kTFUIModalPresentAnimationDuration];
}

+ (void)dismissModalViewControllerCompletion:(TFUIModalPresentViewControllerDismissCompletion)completion {
    
    UIViewController *visibleVC = [TFUIDefine visibleViewController];
    TFUIModalPresentViewController *modalVC = visibleVC.presentedViewController;
    if (!modalVC&&[visibleVC isKindOfClass:[self class]]) {
        modalVC = visibleVC;
    }
    if (completion) {
        modalVC.dismissCompletion = completion;
    }
    [modalVC dismissAnimation];
}


+ (instancetype)showInView:(UIView *)view withAnimationStyle:(TFUIModalPresentAnimationStyle)animationStyle{
    return [self showInView:view withContentView:nil animationStyle:animationStyle animationDuration:kTFUIModalPresentAnimationDuration];
}

+ (instancetype)showInView:(UIView *)view withContentView:(UIView *)contentView animationStyle:(TFUIModalPresentAnimationStyle)animationStyle animationDuration:(float)animationDuration dismissCompletion:(nullable TFUIModalPresentViewControllerDismissCompletion)dismissCompletion {
    TFUIModalPresentViewController *modalVC = [[self alloc] init];
    if (contentView) {
        modalVC.contentView = contentView;
    }
    modalVC.animationStyle = animationStyle;
    modalVC.animationDuration = animationDuration;
    [modalVC loadViewIfNeeded];
    [modalVC beginAppearanceTransition:YES animated:YES];
    view.tfUI_modalPresentViewController = modalVC;
    modalVC.view.frame = view.bounds;
    modalVC.showInView = view;
    modalVC.dismissCompletion = dismissCompletion;
    [view addSubview:modalVC.view];
    [modalVC endAppearanceTransition];
    return modalVC;
}

+ (instancetype)showInView:(UIView *)view withContentView:(UIView *)contentView animationStyle:(TFUIModalPresentAnimationStyle)animationStyle animationDuration:(float)animationDuration {
    return [self showInView:view withContentView:contentView animationStyle:animationStyle animationDuration:animationDuration dismissCompletion:nil];
}

+ (void)dismissModalViewControllerInView:(UIView *)view completion:(TFUIModalPresentViewControllerDismissCompletion)completion {
    if (completion) {
        view.tfUI_modalPresentViewController.dismissCompletion = completion;
    }
    [view.tfUI_modalPresentViewController dismissAnimation];
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
        self.modalPresentationStyle = UIModalPresentationCustom;
        [self didInitialize];
    }
    return self;
}

- (void)didInitialize {
    self.animationStyle = TFUIModalPresentAnimationStyleFade;
    self.animationDuration = 0.6;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor clearColor];
    self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.3];
    [self.view addSubview:self.dimmingView];
    [self.view addSubview:self.contentView];
    [self.view bringSubviewToFront:_contentView];
    [_dimmingView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_equalTo(UIEdgeInsetsZero);
    }];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self showAnimation];
}

- (void)p_dimmingViewDidTapAction:(UITapGestureRecognizer *)sender {
    [self dismissAnimation];
}

- (void)showAnimation {
    switch (self.animationStyle) {
        case TFUIModalPresentAnimationStyleFade:{
            self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
            self.contentView.alpha = 0.0;
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
                self.contentView.alpha = 1.0;
            }];
        }
            break;
        case TFUIModalPresentAnimationStylePopup: {
            self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
            self.contentView.transform = CGAffineTransformMakeScale(0.1, 0.1);
            self.contentView.alpha = 0.0;
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
                self.contentView.transform = CGAffineTransformIdentity;
                self.contentView.alpha = 1.0;
            }];
        }
            break;
        case TFUIModalPresentAnimationStyleSpringPopup: {
            self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
            self.contentView.transform = CGAffineTransformMakeScale(0.1, 0.1);
            self.contentView.alpha = 0.0;
            [UIView animateWithDuration:self.animationDuration+0.3 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:0.5 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
                self.contentView.transform = CGAffineTransformIdentity;
                self.contentView.alpha = 1.0;
            } completion:nil];
        }
            break;
        case TFUIModalPresentAnimationStyleSlide: case TFUIModalPresentAnimationStyleSlideBottomToTop: {
            self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
            self.contentView.transform = CGAffineTransformMakeTranslation(0.0, CGRectGetHeight(self.view.frame)-CGRectGetHeight(self.contentView.frame));
            self.contentView.alpha = 0.0;
            
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
                self.contentView.alpha = 1.0;
                self.contentView.transform = CGAffineTransformIdentity;
            }];
        }
            break;
        case TFUIModalPresentAnimationStyleSlideTopToBottom: {
            self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
            self.contentView.transform = CGAffineTransformMakeTranslation(0.0, -CGRectGetHeight(self.contentView.frame));
            self.contentView.alpha = 0.0;
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
                self.contentView.alpha = 1.0;
                self.contentView.transform = CGAffineTransformIdentity;
            }];
        }
            break;
        case TFUIModalPresentAnimationStyleSlideLeftToRight: {
            self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
            self.contentView.transform = CGAffineTransformMakeTranslation(-CGRectGetWidth(self.contentView.frame), 0.0);
            self.contentView.alpha = 0.0;
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
                self.contentView.alpha = 1.0;
                self.contentView.transform = CGAffineTransformIdentity;
            }];
        }
            break;
        case TFUIModalPresentAnimationStyleSlideRightToLeft: {
            
            self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
            self.contentView.transform = CGAffineTransformMakeTranslation(CGRectGetWidth(self.view.frame)-CGRectGetWidth(self.contentView.frame), 0.0);
            self.contentView.alpha = 0.0;
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
                self.contentView.alpha = 1.0;
                self.contentView.transform = CGAffineTransformIdentity;
            }];
        }
            break;
        default:
            break;
    }
}

- (void)dismissAnimation {
    switch (self.animationStyle) {
        case TFUIModalPresentAnimationStyleFade: {
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
                self.contentView.alpha = 0.0;
            } completion:^(BOOL finished) {
                if (finished) {
                    [self dismissViewController];
                }
            }];
        }
            break;
        case TFUIModalPresentAnimationStylePopup: {
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
                self.contentView.alpha = 0.0;
                self.contentView.transform = CGAffineTransformMakeScale(0.1, 0.1);
            } completion:^(BOOL finished) {
                if (finished) {
                    [self dismissViewController];
                }
            }];
        }
            break;
        case TFUIModalPresentAnimationStyleSpringPopup: {
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
                self.contentView.alpha = 0.0;
                self.contentView.transform = CGAffineTransformMakeScale(0.1, 0.1);
            } completion:^(BOOL finished) {
                if (finished) {
                    [self dismissViewController];
                }
            }];
        }
            break;
        case TFUIModalPresentAnimationStyleSlide: case TFUIModalPresentAnimationStyleSlideBottomToTop: {
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
                self.contentView.transform = CGAffineTransformMakeTranslation(0.0, CGRectGetHeight(self.view.frame)-CGRectGetHeight(self.contentView.frame));
                self.contentView.alpha = 0.0;
            } completion:^(BOOL finished) {
                [self dismissViewController];
            }];
        }
            break;
        case TFUIModalPresentAnimationStyleSlideTopToBottom: {
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
                self.contentView.transform = CGAffineTransformMakeTranslation(0.0, -CGRectGetHeight(self.contentView.frame));
                self.contentView.alpha = 0.0;
            } completion:^(BOOL finished) {
                [self dismissViewController];
            }];
        }
            break;
        case TFUIModalPresentAnimationStyleSlideLeftToRight: {
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
                self.contentView.transform = CGAffineTransformMakeTranslation(-CGRectGetWidth(self.contentView.frame), 0.0);
                self.contentView.alpha = 0.0;
            } completion:^(BOOL finished) {
                [self dismissViewController];
            }];
        }
            break;
        case TFUIModalPresentAnimationStyleSlideRightToLeft: {
            [UIView animateWithDuration:self.animationDuration animations:^{
                self.dimmingView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
                self.contentView.transform = CGAffineTransformMakeTranslation(CGRectGetWidth(self.view.frame)-CGRectGetWidth(self.contentView.frame),0.0);
                self.contentView.alpha = 0.0;
            } completion:^(BOOL finished) {
                [self dismissViewController];
            }];
        }
            break;
        default:
            break;
    }
}

- (void)dismissViewController {
    
    if (self.showInView) {
        [self beginAppearanceTransition:NO animated:NO];
        [self.view removeFromSuperview];
        [self endAppearanceTransition];
        self.showInView.tfUI_modalPresentViewController = nil;
        if (self.dismissCompletion) {
            self.dismissCompletion();
        }
    }
    else {
        typeof(self) __weak weakSelf = self;
        [self dismissViewControllerAnimated:NO completion:^{
            if (weakSelf.dismissCompletion) {
                weakSelf.dismissCompletion();
            }
        }];
    }
}

#pragma mark - lazy load.

- (UIView *)dimmingView {
    if (!_dimmingView) {
        _dimmingView = [[UIView alloc] init];
        [_dimmingView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(p_dimmingViewDidTapAction:)]];
    }
    return _dimmingView;
}

- (UIView *)contentView {
    if (!_contentView) {
        _contentView = [[UIView alloc] init];
    }
    return _contentView;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

@implementation UIView (UIModalPresent)

- (void)setTfUI_modalPresentViewController:(TFUIModalPresentViewController *)tfUI_modalPresentViewController {
    objc_setAssociatedObject(self, @selector(tfUI_modalPresentViewController), tfUI_modalPresentViewController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (TFUIModalPresentViewController *)tfUI_modalPresentViewController {
    return objc_getAssociatedObject(self, _cmd);
}

@end
